import os
import random
import math
import time

import cv2 as cv
import numpy as np
import creater.creatorMain
width = 1024
height = 1280


def rand_center(radius):
    x = random.randint(radius, width - 2 * radius)
    y = random.randint(radius, height - 2 * radius)
    return [y, x]


def add_guassian_noise(img, mean, stddev):
    noise = np.random.normal(mean, stddev, img.shape).astype(np.uint8)
    noisy_image = cv.add(img, noise)
    return np.clip(noisy_image, 0, 255).astype(np.uint8)


def add_salt_and_pepper_noise(image, center, radius, noise_ratio):
    noisy_pixels = int(noise_ratio * image.size)
    for _ in range(noisy_pixels):
        row = np.random.randint(0, image.shape[0])
        col = np.random.randint(0, image.shape[1])
        if np.random.rand() < 0.5:
            image[row, col] = 0  # 设置为黑色
        else:
            image[row, col] = 255  # 设置为白色


def add_stain(image, max_stain_size, num_stains):
    for _ in range(num_stains):
        stain_size = np.random.randint(1, max_stain_size)  # 污渍的大小
        stain_color = np.random.randint(0, 256)  # 污渍的灰度级别
        position = (np.random.randint(0, image.shape[1]), np.random.randint(0, image.shape[0]))  # 污渍的位置
        cv.circle(image, position, stain_size, stain_color, -1)


def add_stain2(image, max_stain_size, num_stains):
    for _ in range(num_stains):
        stain_size = np.random.randint(1, max_stain_size)  # 污渍的大小
        position = (np.random.randint(0, image.shape[1]), np.random.randint(0, image.shape[0]))  # 污渍的位置
        # 创建一个和原始图像大小相同的黑色图像作为遮罩
        mask = np.zeros_like(image)
        # 在遮罩上随机绘制一些白色的不规则形状
        cv.circle(mask, position, stain_size, 255, -1)
        cv.ellipse(mask, position, (int(stain_size / 2), int(stain_size * 1.5)), 0, 0, 360, 255, -1)
        # 对遮罩进行形态学膨胀操作，使得不规则形状更加突出
        kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))
        mask = cv.dilate(mask, kernel)
        # 将遮罩应用到原始图像上，生成污渍效果
        image[mask > 0] = np.random.randint(0, 256)


def create_img_by_img():
    # 读取原始图像并转换为灰度图像
    image = cv.imread('/home/mikoptik/yolov7_test/yolo_v7/realData/23.05.26/circlesring//34.bmp', cv.IMREAD_GRAYSCALE)
    # 获取原始图像的灰度值分布直方图
    hist = cv.calcHist([image], [0], None, [256], [0, 256])
    # 计算累积直方图
    cdf = hist.cumsum()
    # 归一化累积直方图
    cdf_normalized = cdf / cdf.max()
    # 生成随机数列
    random_values = np.random.rand(image.shape[0] * image.shape[1])
    # 根据灰度值分布对随机数列进行排序
    sorted_values = np.interp(random_values, cdf_normalized, np.arange(0, 256))
    # 将排序后的值重塑为与原始图像相同大小的矩阵
    sorted_image = np.reshape(sorted_values, image.shape).astype(np.uint8)
    return sorted_image


def point_to_center_dis(point, center_):
    return math.sqrt(math.pow((point[0] - center_[0]), 2) + math.pow((point[1] - center_[1]), 2))


def add_noise(img, xminp, xmaxp, yminp, ymaxp, center, radius, noise_random):
    for ii in range(xminp, xmaxp):
        for jj in range(yminp, ymaxp):
            point_ = [ii, jj]
            if point_to_center_dis(point_, center) <= radius + 2:
                if np.random.rand() < noise_random:
                    # img[jj, ii] = random.randint(55, 87)
                    if np.random.rand() < 0.5:
                        img[jj, ii] = random.randint(0, 100)
                    else:
                        img[jj, ii] = random.randint(130, 255)
                    # if np.random.rand() < 0.5:
                    #     img[jj, ii] = 0  # 设置为黑色
                    # else:
                    #     img[jj, ii] = 255  # 设置为白色


def wirite_img(radius, center, _file_path, _j, _res_file):
    # flag = random.randint(0, 1)
    # color = np.random.randint(50, 256)
    # color = random.randint(30, 40)
    # img = create_img_by_img()
    color = 40 if np.random.rand() < 0.6 else 230
    img = creater.creatorMain.create_img_random()
    # img = np.zeros((width, height), dtype=np.uint8)
    # if color > 255 else 255 * np.zeros((width, height), dtype=np.uint8)
    # 逐个像素随机赋值
    # for y in range(height):
    #     for x in range(width):
    #         # 生成随机灰度值
    #         gray_value = np.random.randint(0, 256)
    #         # 赋值给图像的对应像素
    #         img[x, y] = gray_value
    # -1填充圆形
    cv.circle(img, (center[0], center[1]), radius, color, -1, cv.LINE_AA)
    centerx = center[0] / height
    centery = center[1] / width
    dx = (2 * radius) / height
    dy = (2 * radius) / width
    _res_file.write("0" + ' ')
    _res_file.write(str(centerx) + ' ')
    _res_file.write(str(centery) + ' ')
    _res_file.write(str(dx) + ' ')
    _res_file.write(str(dy) + ' ')
    xminp = (center[0] - radius)
    yminp = (center[1] - radius)
    xmaxp = (center[0] + radius)
    ymaxp = (center[1] + radius)
    # cv.rectangle(img, (xminp, yminp), (xmaxp, ymaxp), color, 5)
    # xmin = (center[0] - radius) / height
    # ymin = (center[1] - radius) / width
    # xmax = (center[0] + radius) / height
    # ymax = (center[1] + radius) / width
    # _res_file.write("0" + ' ')
    # _res_file.write(str(xmin) + ' ')
    # _res_file.write(str(ymin) + ' ')
    # _res_file.write(str(xmax) + ' ')
    # _res_file.write(str(ymax) + ' ')

    # _tfile.write("name: " + str(_j) + '.bmp')
    # _tfile.write("    center_point: " + str(center[0]) + "," + str(center[1]))
    # _tfile.write("    radius: " + str(radius) + "\n")
    # add_stain2(img, 50, 20)
    ksize = (3, 3)
    sigma = 0
    # add_salt_and_pepper_noise(img, center, radius, 0.8)
    if radius < 80:
        noise_random = 0.3
    else:
        noise_random = 0.5
    add_noise(img, xminp, xmaxp, yminp, ymaxp, center, radius, noise_random)
    blurred = cv.GaussianBlur(img, ksize, sigma)
    cv.imwrite(_file_path, blurred)


def create(_file_path, _j, res_path):
    radius = random.randint(30, 200)
    center = rand_center(radius)
    wirite_img(radius, center, _file_path, _j, res_path)


def rand_create_circle(dir_nums, img_nums, root_path):
    for i in range(1, dir_nums + 1):
        folder_path = os.path.join(root_path, str(i))
        res_path_d = os.path.join(folder_path, "res")
        # txt_path = os.path.join(folder_path, str(i) + '.txt')
        print(i, " begin")
        if not os.path.exists(folder_path):
            os.makedirs(folder_path)
        if not os.path.exists(res_path_d):
            os.makedirs(res_path_d)
        # file = open(txt_path, 'w')
        for j in range(1, img_nums + 1):
            start_time = time.time()
            if not os.path.exists(folder_path):
                os.makedirs(folder_path)
            file_path = os.path.join(folder_path, "scn"+str(j) + '.bmp')
            res_path = os.path.join(res_path_d, "scn"+str(j) + ".txt")
            res_file = open(res_path, 'w')
            create(file_path, j, res_file)
            end_time = time.time()
            if j % 100 == 0:
                print(j, "-->finish", "time-->", end_time - start_time, '/pcs')


if __name__ == '__main__':
    root_dir = "/home/mikoptik/yolov7_test/yolo_v7/match_circle"  #match_circle
    dir_num = 1
    img_num = 5000
    rand_create_circle(dir_num, img_num, root_dir)
